#include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<stdio.h>

using namespace std;

/*
fork指令==============================
fork拥有两个返回值，父子进程的代码是共享的，数据给自开辟空间
私有一份
*/
//fork之后通常要使用if进行分流
//僵尸状态：
/*
这是一个比较特殊的状态，当父进程退出并且父进程没有读取到子进车给
退出的返回值，这时就会产生僵尸进程
僵尸进程会以终止状态保持在进程表当中并且会一直等待父进程读取
退出状态码，所以只要子进程退出父进程还在运行，但是夫进车给没有
读取到子进程状态，子进程就会进入僵尸状态

============================
while :; do ps ajx | head -1 && ps ajx | grep mytest |
 grep -v grep; sleep 1;echo "-------------------";done
 grep -v grep 的作用就是去除包含grep的进程行，也就是让显示的
 信息更加简洁
*/
//僵尸进程的危害
/*
进程的退出状态必须被维持下去，因为他要告诉父进程，你交给我的
任务我完成的如何，如果父进程一直不读取那么子进程就会一直陷入
僵尸进程，pcb也会一直维护者他的状态，而且这本身就要占用内存
======================孤儿进程
父进程如果提前退出的话，那么子进程被遗留就叫做孤儿进程

========================进程的优先级
ps -l命令会输出进程的优先级等属性
PRI代表进程的优先级，他的值越小越早被执行，换言之优先级越高
*/
/*
通过代码来获取环境变量：
*/


//====================================
//====================================
//进程的概念这里的环境变量内容还需要重新巩固
//====================================
//====================================


// int main(int args,char* argv[],char* env[])
// {
//     extern char** environ;
//     int i=0;
//     for(;env[i];i++)
//     {
//         cout<<"env[i]:"<<environ[i];
//     }
//     cout<<endl;
//     return 0;
// }

// int main()
// {
//     pid_t id=fork();
//     if( id < 0)
//     {
//         perror("fork()");
//         exit(-1);
//     }
//     else if(id == 0)
//     {
//         cout<<"i am a child["<<getpid()<<"]"<<endl;
//         sleep(10);
//     }
//     else
//     {
//         cout<<"i am a parent["<<getpid()<<"]"<<endl;
//         sleep(1);
//         exit(0);
//     }
//     return 0;
// }
// int main()
// {
//     pid_t id=fork();
//     if(id < 0)
//     {
//         perror("fork()");
//         exit(-1);
//     }
//     else if(id > 0)
//     {
//         cout<<"parent["<<getpid()<<"] is sleeping"<<endl;
//         sleep(60);
//     }
//     else
//     {
//         cout<<"child["<<getpid()<<"] is begin"<<endl;
//         sleep(1);
//         exit(EXIT_SUCCESS);
//     }
//     return 0;
// }
// int main()
// {
//     int ret=fork();
//     if(ret < 0)
//     {
//         perror("fork");
//         return 1;
//     }
//     else if(ret == 0)
//     {
//         cout<<"I am a child:["<<getpid()<<"] "<<"ret:"<<ret<<endl;
//     }
//     else
//     {
//         cout<<"I am a father:["<<getpid()<<"] "<<"ret:"<<ret<<endl;
//     }
//     //ret 对于父进程来说时返回子进程的pid但是对于子进程来说
//     //却是返回0
//     sleep(1);
//     return 0;
// }
// int main()
// {
//     int ret=fork();
//     cout<<"hello proc:"<<getpid()<<"ret:"<<ret<<endl;
//     sleep(1);
//     return 0;
// }
// int main()
// {
//     while(true)
//     {
//         sleep(3);
//         cout<<"hello yangyi"<<endl;
//     }
//     return 0;
// }
/*
系统调用和库函数的概念：
    在开发角度，操作系统对外会表现为一个整体，但是会暴漏出自己的
部分接口，供上层开发者使用，有操作系统提供的接口叫做系统调用
    操作系统调用在使用上功能比较基础，对用户的要求也比较高
所以有心的开发者可以对部分的系统调用进行封装，从而形成库，从而
有了库，就很利于更上层用户或者开发者进行二次开发
    操作系统对于进程的管理就是先描述再组织
进程基本概念========================
课本：程序的一个执行实例，正在执行的程序
内核观点：担当分配系统资源的实体
描述进程PCB：
进程信息被存放在一个叫做进程控制块的结构体当中，可以理解为
属性的集合，进程的控制块也就是这个结构体会被加载到内存当中
里面包含着进程的各种信息
进程控制块的内容分类：
标识符：描述进程的唯一标识符，用来区别所有的进程
状态：任务状态，退出代码退出信号等等
优先级：相对于其他的进程的优先级
程序计数器：进程当中要被执行的下一条指令
内存指针：包括进程代码和进程相关数据的指针，还有和其他进程
共享内存块的指针
上下文数据：进车给执行时处理器的寄存器中的数据
进程所有的信息都可以通过proc文件夹来查看

//获取进程时通过top和ps这些用户级工具
拓展ps用户级工具：
ps:只会显示默认进程id，还有运行终端和CPU执行时间
ps -aux:显示所有的进程信息
进程常见的几种状态：
D:不可中断
R：正在运行
S:休眠
T:停止
Z:僵尸进程

grep:这里代表查看指定的相关进程
*/